﻿/********************** File Header *****************\
File Name : <DoubleMeta Phonet>
Project Name : <Mobwiz.SpellChecker.Net>
Author : <Dove>
Description : Description
Change log :
------------------------------------------------
#1 2012-6-21 
#2 

**/


namespace Mobwiz.SpellChecker.Core.Phonets
{
    using System;
    using System.Linq;
    using System.Text;

    public class DoubleMetaPhonet : IPhonet
    {
        private static readonly char[] replaceList = { 'A', 'B', 'X', 'S', 'K', 'J', 'T', 'F', 'H', 'L', 'M', 'N', 'P', 'R', '0' };
        private static readonly String[] myList = { "GN", "KN", "PN", "WR", "PS", "" };
        private static readonly String[] list1 = { "ACH", "" };
        private static readonly String[] list2 = { "BACHER", "MACHER", "" };
        private static readonly String[] list3 = { "CAESAR", "" };
        private static readonly String[] list4 = { "CHIA", "" };
        private static readonly String[] list5 = { "CH", "" };
        private static readonly String[] list6 = { "CHAE", "" };
        private static readonly String[] list7 = { "HARAC", "HARIS", "" };
        private static readonly String[] list8 = { "HOR", "HYM", "HIA", "HEM", "" };
        private static readonly String[] list9 = { "CHORE", "" };
        private static readonly String[] list10 = { "VAN ", "VON ", "" };
        private static readonly String[] list11 = { "SCH", "" };
        private static readonly String[] list12 = { "ORCHES", "ARCHIT", "ORCHID", "" };
        private static readonly String[] list13 = { "T", "S", "" };
        private static readonly String[] list14 = { "A", "O", "U", "E", "" };
        private static readonly String[] list15 = { "L", "R", "N", "M", "B", "H", "F", "V", "W", " ", "" };
        private static readonly String[] list16 = { "MC", "" };
        private static readonly String[] list17 = { "CZ", "" };
        private static readonly String[] list18 = { "WICZ", "" };
        private static readonly String[] list19 = { "CIA", "" };
        private static readonly String[] list20 = { "CC", "" };
        private static readonly String[] list21 = { "I", "E", "H", "" };
        private static readonly String[] list22 = { "HU", "" };
        private static readonly String[] list23 = { "UCCEE", "UCCES", "" };
        private static readonly String[] list24 = { "CK", "CG", "CQ", "" };
        private static readonly String[] list25 = { "CI", "CE", "CY", "" };
        // DMV: used by the orininal code which returned two phonetic code, but not the current code
        //    private static  String[] list26 = {
        //        "CIO", "CIE", "CIA", ""
        //    };       
        private static readonly String[] list27 = { " C", " Q", " G", "" };
        private static readonly String[] list28 = { "C", "K", "Q", "" };
        private static readonly String[] list29 = { "CE", "CI", "" };
        private static readonly String[] list30 = { "DG", "" };
        private static readonly String[] list31 = { "I", "E", "Y", "" };
        private static readonly String[] list32 = { "DT", "DD", "" };
        private static readonly String[] list33 = { "B", "H", "D", "" };
        private static readonly String[] list34 = { "B", "H", "D", "" };
        private static readonly String[] list35 = { "B", "H", "" };
        private static readonly String[] list36 = { "C", "G", "L", "R", "T", "" };
        private static readonly String[] list37 = { "EY", "" };
        private static readonly String[] list38 = { "LI", "" };
        private static readonly String[] list39 = { "ES", "EP", "EB", "EL", "EY", "IB", "IL", "IN", "IE", "EI", "ER", "" };
        private static readonly String[] list40 = { "ER", "" };
        private static readonly String[] list41 = { "DANGER", "RANGER", "MANGER", "" };
        private static readonly String[] list42 = { "E", "I", "" };
        private static readonly String[] list43 = { "RGY", "OGY", "" };
        private static readonly String[] list44 = { "E", "I", "Y", "" };
        private static readonly String[] list45 = { "AGGI", "OGGI", "" };
        private static readonly String[] list46 = { "VAN ", "VON ", "" };
        private static readonly String[] list47 = { "SCH", "" };
        private static readonly String[] list48 = { "ET", "" };
        //  DMV: used breadonly y the orininal code which returned two phonetic code, but not the current code
        //    private sreadonly tatic  String[] list49 = {
        //        "IER ", ""
        //    };
        private static readonly String[] list50 = { "JOSE", "" };
        private static readonly String[] list51 = { "SAN ", "" };
        private static readonly String[] list52 = { "SAN ", "" };
        private static readonly String[] list53 = { "JOSE", "" };
        private static readonly String[] list54 = { "L", "T", "K", "S", "N", "M", "B", "Z", "" };
        private static readonly String[] list55 = { "S", "K", "L", "" };
        private static readonly String[] list56 = { "ILLO", "ILLA", "ALLE", "" };
        private static readonly String[] list57 = { "AS", "OS", "" };
        private static readonly String[] list58 = { "A", "O", "" };
        private static readonly String[] list59 = { "ALLE", "" };
        private static readonly String[] list60 = { "UMB", "" };
        private static readonly String[] list61 = { "ER", "" };
        private static readonly String[] list62 = { "P", "B", "" };
        private static readonly String[] list63 = { "IE", "" };
        private static readonly String[] list64 = { "ME", "MA", "" };
        private static readonly String[] list65 = { "ISL", "YSL", "" };
        private static readonly String[] list66 = { "SUGAR", "" };
        private static readonly String[] list67 = { "SH", "" };
        private static readonly String[] list68 = { "HEIM", "HOEK", "HOLM", "HOLZ", "" };
        private static readonly String[] list69 = { "SIO", "SIA", "" };
        private static readonly String[] list70 = { "SIAN", "" };
        private static readonly String[] list71 = { "M", "N", "L", "W", "" };
        private static readonly String[] list72 = { "Z", "" };
        private static readonly String[] list73 = { "Z", "" };
        private static readonly String[] list74 = { "SC", "" };
        private static readonly String[] list75 = { "OO", "ER", "EN", "UY", "ED", "EM", "" };
        private static readonly String[] list76 = { "ER", "EN", "" };
        private static readonly String[] list77 = { "I", "E", "Y", "" };
        private static readonly String[] list78 = { "AI", "OI", "" };
        private static readonly String[] list79 = { "S", "Z", "" };
        private static readonly String[] list80 = { "TION", "" };
        private static readonly String[] list81 = { "TIA", "TCH", "" };
        private static readonly String[] list82 = { "TH", "" };
        private static readonly String[] list83 = { "TTH", "" };
        private static readonly String[] list84 = { "OM", "AM", "" };
        private static readonly String[] list85 = { "VAN ", "VON ", "" };
        private static readonly String[] list86 = { "SCH", "" };
        private static readonly String[] list87 = { "T", "D", "" };
        private static readonly String[] list88 = { "WR", "" };
        private static readonly String[] list89 = { "WH", "" };
        private static readonly String[] list90 = { "EWSKI", "EWSKY", "OWSKI", "OWSKY", "" };
        private static readonly String[] list91 = { "SCH", "" };
        private static readonly String[] list92 = { "WICZ", "WITZ", "" };
        private static readonly String[] list93 = { "IAU", "EAU", "" };
        private static readonly String[] list94 = { "AU", "OU", "" };
        private static readonly String[] list95 = { "C", "X", "" };

        //  DMV: used breadonly y the orininal code which returned two phonetic code, but not the current code
        //    private static  String[] list96 = {
        //        "ZO", "ZI", "ZA", ""
        //    };

        /**
         * put your documentation comment here
         * @return
         */

        private static bool SlavoGermanic(String ins)
        {
            if ((ins.IndexOf("W") > -1) || (ins.IndexOf("K") > -1) || (ins.IndexOf("CZ") > -1) || (ins.IndexOf("WITZ") > -1))
                return true;
            return false;
        }

        /**
         * put your documentation comment here
         * @param main
         */
        private static void MetaphAdd(StringBuilder primary, String main)
        {
            if (main != null)
            {
                primary.Append(main);
            }
        }

        private static void MetaphAdd(StringBuilder primary, char main)
        {
            primary.Append(main);
        }

        /**
         * put your documentation comment here
         * @param at
         * @return
         */
        private static bool isVowel(String ins, int at, int length)
        {
            if ((at < 0) || (at >= length))
                return false;
            char it = (ins.ToCharArray())[at];
            if ((it == 'A') || (it == 'E') || (it == 'I') || (it == 'O') || (it == 'U') || (it == 'Y'))
                return true;
            return false;
        }

        /**
         * put your documentation comment here
         * @param string
         * @param start
         * @param length
         * @param list
         * @return
         */
        private static bool stringAt(String str, int start, int length, String[] list)
        {
            if ((start < 0) || (start >= str.Length) || list.Count() == 0)
                return false;
            String substr = str.Substring(start, length); // the Substring here is different from the substring in the Java
            for (int i = 0; i < list.Count(); i++)
            {
                if (list[i].Equals(substr))
                    return true;
            }
            return false;
        }

      
        #region IPhonet Members

        public char[] GetReplaceList()
        {
            return replaceList;
        }
        /**
       * Take the given word, and return the best phonetic hash for it.
       * Vowels are minimized as much as possible, and consenants
       * that have similiar sounds are converted to the same consenant
       * for example, 'v' and 'f' are both converted to 'f'
       * @param word the texte to transform
       * @return the result of the phonetic transformation
       */
        public string Transform(string originalWord)
        {
            StringBuilder primary = new StringBuilder(originalWord.Length + 5);
            String ins = originalWord.ToUpperInvariant() + "     ";
            int current = 0;
            int length = ins.Length;
            if (length < 1)
                return "";
            int last = length - 1;
            bool isSlavoGermaic = SlavoGermanic(ins);
            if (stringAt(ins, 0, 2, myList))
                current += 1;
            if (ins.ToCharArray()[0] == 'X')
            {
                MetaphAdd(primary, 'S');
                current += 1;
            }
            while (current < length)
            {
                switch (ins.ToCharArray()[current])
                {
                    case 'A':
                    case 'E':
                    case 'I':
                    case 'O':
                    case 'U':
                    case 'Y':
                        if (current == 0)
                            MetaphAdd(primary, 'A');
                        current += 1;
                        break;
                    case 'B':
                        MetaphAdd(primary, 'P');
                        if (ins.ToCharArray()[current + 1] == 'B')
                            current += 2;
                        else
                            current += 1;
                        break;
                    case '\u00C7':
                        MetaphAdd(primary, 'S');
                        current += 1;
                        break;
                    case 'C':
                        if ((current > 1) && !isVowel(ins, current - 2, length) && stringAt(ins, (current - 1), 3, list1) && (ins.ToCharArray()[current + 2] != 'I') && (ins.ToCharArray()[current + 2] != 'E') || stringAt(ins, (current - 2), 6, list2))
                        {
                            MetaphAdd(primary, 'K');
                            current += 2;
                            break;
                        }
                        if ((current == 0) && stringAt(ins, current, 6, list3))
                        {
                            MetaphAdd(primary, 'S');
                            current += 2;
                            break;
                        }
                        if (stringAt(ins, current, 4, list4))
                        {
                            MetaphAdd(primary, 'K');
                            current += 2;
                            break;
                        }
                        if (stringAt(ins, current, 2, list5))
                        {
                            if ((current > 0) && stringAt(ins, current, 4, list6))
                            {
                                MetaphAdd(primary, 'K');
                                current += 2;
                                break;
                            }
                            if ((current == 0) && stringAt(ins, (current + 1), 5, list7) || stringAt(ins, current + 1, 3, list8) && !stringAt(ins, 0, 5, list9))
                            {
                                MetaphAdd(primary, 'K');
                                current += 2;
                                break;
                            }
                            if (stringAt(ins, 0, 4, list10) || stringAt(ins, 0, 3, list11) || stringAt(ins, current - 2, 6, list12) || stringAt(ins, current + 2, 1, list13) || (stringAt(ins, current - 1, 1, list14) || (current == 0)) && stringAt(ins, current + 2, 1, list15))
                            {
                                MetaphAdd(primary, 'K');
                            }
                            else
                            {
                                if (current > 0)
                                {
                                    if (stringAt(ins, 0, 2, list16))
                                        MetaphAdd(primary, 'K');
                                    else
                                        MetaphAdd(primary, 'X');
                                }
                                else
                                {
                                    MetaphAdd(primary, 'X');
                                }
                            }
                            current += 2;
                            break;
                        }
                        if (stringAt(ins, current, 2, list17) && !stringAt(ins, current, 4, list18))
                        {
                            MetaphAdd(primary, 'S');
                            current += 2;
                            break;
                        }
                        if (stringAt(ins, current, 2, list19))
                        {
                            MetaphAdd(primary, 'X');
                            current += 2;
                            break;
                        }
                        if (stringAt(ins, current, 2, list20) && !((current == 1) && ins.ToCharArray()[0] == 'M'))
                        {
                            if (stringAt(ins, current + 2, 1, list21) && !stringAt(ins, current + 2, 2, list22))
                            {
                                if (((current == 1) && (ins.ToCharArray()[current - 1] == 'A')) || stringAt(ins, (current - 1), 5, list23))
                                    MetaphAdd(primary, "KS");
                                else
                                    MetaphAdd(primary, 'X');
                                current += 3;
                                break;
                            }
                            else
                            {
                                MetaphAdd(primary, 'K');
                                current += 2;
                                break;
                            }
                        }
                        if (stringAt(ins, current, 2, list24))
                        {
                            MetaphAdd(primary, 'K');
                            current += 2;
                            break;
                        }
                        else if (stringAt(ins, current, 2, list25))
                        {
                            MetaphAdd(primary, 'S');
                            current += 2;
                            break;
                        }

                        MetaphAdd(primary, 'K');
                        if (stringAt(ins, current + 1, 2, list27))
                            current += 3;
                        else if (stringAt(ins, current + 1, 1, list28) && !stringAt(ins, current + 1, 2, list29))
                            current += 2;
                        else
                            current += 1;
                        break;
                    case 'D':
                        if (stringAt(ins, current, 2, list30))
                        {
                            if (stringAt(ins, current + 2, 1, list31))
                            {
                                MetaphAdd(primary, 'J');
                                current += 3;
                                break;
                            }
                            else
                            {
                                MetaphAdd(primary, "TK");
                                current += 2;
                                break;
                            }
                        }
                        MetaphAdd(primary, 'T');
                        if (stringAt(ins, current, 2, list32))
                        {
                            current += 2;
                        }
                        else
                        {
                            current += 1;
                        }
                        break;
                    case 'F':
                        if (ins.ToCharArray()[current + 1] == 'F')
                            current += 2;
                        else
                            current += 1;
                        MetaphAdd(primary, 'F');
                        break;
                    case 'G':
                        if (ins.ToCharArray()[current + 1] == 'H')
                        {
                            if ((current > 0) && !isVowel(ins, current - 1, length))
                            {
                                MetaphAdd(primary, 'K');
                                current += 2;
                                break;
                            }
                            if (current < 3)
                            {
                                if (current == 0)
                                {
                                    if (ins.ToCharArray()[current + 2] == 'I')
                                        MetaphAdd(primary, 'J');
                                    else
                                        MetaphAdd(primary, 'K');
                                    current += 2;
                                    break;
                                }
                            }
                            if ((current > 1) && stringAt(ins, current - 2, 1, list33) || ((current > 2) && stringAt(ins, current - 3, 1, list34)) || ((current > 3) && stringAt(ins, current - 4, 1, list35)))
                            {
                                current += 2;
                                break;
                            }
                            else
                            {
                                if ((current > 2) && (ins.ToCharArray()[current - 1] == 'U') && stringAt(ins, current - 3, 1, list36))
                                {
                                    MetaphAdd(primary, 'F');
                                }
                                else
                                {
                                    if ((current > 0) && (ins.ToCharArray()[current - 1] != 'I'))
                                        MetaphAdd(primary, 'K');
                                }
                                current += 2;
                                break;
                            }
                        }
                        if (ins.ToCharArray()[current + 1] == 'N')
                        {
                            if ((current == 1) && isVowel(ins, 0, length) && !isSlavoGermaic)
                            {
                                MetaphAdd(primary, "KN");
                            }
                            else
                            {
                                if (!stringAt(ins, current + 2, 2, list37) && (ins.ToCharArray()[current + 1] != 'Y') && !isSlavoGermaic)
                                {
                                    MetaphAdd(primary, "N");
                                }
                                else
                                {
                                    MetaphAdd(primary, "KN");
                                }
                            }
                            current += 2;
                            break;
                        }
                        if (stringAt(ins, current + 1, 2, list38) && !isSlavoGermaic)
                        {
                            MetaphAdd(primary, "KL");
                            current += 2;
                            break;
                        }
                        if ((current == 0) && ((ins.ToCharArray()[current + 1] == 'Y') || stringAt(ins, current + 1, 2, list39)))
                        {
                            MetaphAdd(primary, 'K');
                            current += 2;
                            break;
                        }
                        if ((stringAt(ins, current + 1, 2, list40) || (ins.ToCharArray()[current + 1] == 'Y')) && !stringAt(ins, 0, 6, list41) && !stringAt(ins, current - 1, 1, list42) && !stringAt(ins, current - 1, 3, list43))
                        {
                            MetaphAdd(primary, 'K');
                            current += 2;
                            break;
                        }
                        if (stringAt(ins, current + 1, 1, list44) || stringAt(ins, current - 1, 4, list45))
                        {
                            if (stringAt(ins, 0, 4, list46) || stringAt(ins, 0, 3, list47) || stringAt(ins, current + 1, 2, list48))
                            {
                                MetaphAdd(primary, 'K');
                            }
                            else
                            {
                                MetaphAdd(primary, 'J');
                            }
                            current += 2;
                            break;
                        }
                        if (ins.ToCharArray()[current + 1] == 'G')
                            current += 2;
                        else
                            current += 1;
                        MetaphAdd(primary, 'K');
                        break;
                    case 'H':
                        if (((current == 0) || isVowel(ins, current - 1, length)) && isVowel(ins, current + 1, length))
                        {
                            MetaphAdd(primary, 'H');
                            current += 2;
                        }
                        else
                        {
                            current += 1;
                        }
                        break;
                    case 'J':
                        if (stringAt(ins, current, 4, list50) || stringAt(ins, 0, 4, list51))
                        {
                            if ((current == 0) && (ins.ToCharArray()[current + 4] == ' ') || stringAt(ins, 0, 4, list52))
                            {
                                MetaphAdd(primary, 'H');
                            }
                            else
                            {
                                MetaphAdd(primary, 'J');
                            }
                            current += 1;
                            break;
                        }
                        if ((current == 0) && !stringAt(ins, current, 4, list53))
                        {
                            MetaphAdd(primary, 'J');
                        }
                        else
                        {
                            if (isVowel(ins, current - 1, length) && !isSlavoGermaic && ((ins.ToCharArray()[current + 1] == 'A') || ins.ToCharArray()[current + 1] == 'O'))
                            {
                                MetaphAdd(primary, 'J');
                            }
                            else
                            {
                                if (current == last)
                                {
                                    MetaphAdd(primary, 'J');
                                }
                                else
                                {
                                    if (!stringAt(ins, current + 1, 1, list54) && !stringAt(ins, current - 1, 1, list55))
                                    {
                                        MetaphAdd(primary, 'J');
                                    }
                                }
                            }
                        }
                        if (ins.ToCharArray()[current + 1] == 'J')
                            current += 2;
                        else
                            current += 1;
                        break;
                    case 'K':
                        if (ins.ToCharArray()[current + 1] == 'K')
                            current += 2;
                        else
                            current += 1;
                        MetaphAdd(primary, 'K');
                        break;
                    case 'L':
                        if (ins.ToCharArray()[current + 1] == 'L')
                        {
                            if (((current == (length - 3)) && stringAt(ins, current - 1, 4, list56)) || ((stringAt(ins, last - 1, 2, list57) || stringAt(ins, last, 1, list58)) && stringAt(ins, current - 1, 4, list59)))
                            {
                                MetaphAdd(primary, 'L');
                                current += 2;
                                break;
                            }
                            current += 2;
                        }
                        else
                            current += 1;
                        MetaphAdd(primary, 'L');
                        break;
                    case 'M':
                        if ((stringAt(ins, current - 1, 3, list60) && (((current + 1) == last) || stringAt(ins, current + 2, 2, list61))) || (ins.ToCharArray()[current + 1] == 'M'))
                            current += 2;
                        else
                            current += 1;
                        MetaphAdd(primary, 'M');
                        break;
                    case 'N':
                        if (ins.ToCharArray()[current + 1] == 'N')
                            current += 2;
                        else
                            current += 1;
                        MetaphAdd(primary, 'N');
                        break;
                    case '\u00D1':
                        current += 1;
                        MetaphAdd(primary, 'N');
                        break;
                    case 'P':
                        if (ins.ToCharArray()[current + 1] == 'N')
                        {
                            MetaphAdd(primary, 'F');
                            current += 2;
                            break;
                        }
                        if (stringAt(ins, current + 1, 1, list62))
                            current += 2;
                        else
                            current += 1;
                        MetaphAdd(primary, 'P');
                        break;
                    case 'Q':
                        if (ins.ToCharArray()[current + 1] == 'Q')
                            current += 2;
                        else
                            current += 1;
                        MetaphAdd(primary, 'K');
                        break;
                    case 'R':
                        if ((current == last) && !isSlavoGermaic && stringAt(ins, current - 2, 2, list63) && !stringAt(ins, current - 4, 2, list64))
                        {
                            //            MetaphAdd(primary, "");
                        }
                        else
                            MetaphAdd(primary, 'R');
                        if (ins.ToCharArray()[current + 1] == 'R')
                            current += 2;
                        else
                            current += 1;
                        break;
                    case 'S':
                        if (stringAt(ins, current - 1, 3, list65))
                        {
                            current += 1;
                            break;
                        }
                        if ((current == 0) && stringAt(ins, current, 5, list66))
                        {
                            MetaphAdd(primary, 'X');
                            current += 1;
                            break;
                        }
                        if (stringAt(ins, current, 2, list67))
                        {
                            if (stringAt(ins, current + 1, 4, list68))
                                MetaphAdd(primary, 'S');
                            else
                                MetaphAdd(primary, 'X');
                            current += 2;
                            break;
                        }
                        if (stringAt(ins, current, 3, list69) || stringAt(ins, current, 4, list70))
                        {
                            MetaphAdd(primary, 'S');
                            current += 3;
                            break;
                        }
                        if (((current == 0) && stringAt(ins, current + 1, 1, list71)) || stringAt(ins, current + 1, 1, list72))
                        {
                            MetaphAdd(primary, 'S');
                            if (stringAt(ins, current + 1, 1, list73))
                                current += 2;
                            else
                                current += 1;
                            break;
                        }
                        if (stringAt(ins, current, 2, list74))
                        {
                            if (ins.ToCharArray()[current + 2] == 'H')
                                if (stringAt(ins, current + 3, 2, list75))
                                {
                                    if (stringAt(ins, current + 3, 2, list76))
                                    {
                                        MetaphAdd(primary, "X");
                                    }
                                    else
                                    {
                                        MetaphAdd(primary, "SK");
                                    }
                                    current += 3;
                                    break;
                                }
                                else
                                {
                                    MetaphAdd(primary, 'X');
                                    current += 3;
                                    break;
                                }
                            if (stringAt(ins, current + 2, 1, list77))
                            {
                                MetaphAdd(primary, 'S');
                                current += 3;
                                break;
                            }
                            MetaphAdd(primary, "SK");
                            current += 3;
                            break;
                        }
                        if ((current == last) && stringAt(ins, current - 2, 2, list78))
                        {
                            //MetaphAdd(primary, "");
                        }
                        else
                            MetaphAdd(primary, 'S');
                        if (stringAt(ins, current + 1, 1, list79))
                            current += 2;
                        else
                            current += 1;
                        break;
                    case 'T':
                        if (stringAt(ins, current, 4, list80))
                        {
                            MetaphAdd(primary, 'X');
                            current += 3;
                            break;
                        }
                        if (stringAt(ins, current, 3, list81))
                        {
                            MetaphAdd(primary, 'X');
                            current += 3;
                            break;
                        }
                        if (stringAt(ins, current, 2, list82) || stringAt(ins, current, 3, list83))
                        {
                            if (stringAt(ins, (current + 2), 2, list84) || stringAt(ins, 0, 4, list85) || stringAt(ins, 0, 3, list86))
                            {
                                MetaphAdd(primary, 'T');
                            }
                            else
                            {
                                MetaphAdd(primary, '0');
                            }
                            current += 2;
                            break;
                        }
                        if (stringAt(ins, current + 1, 1, list87))
                        {
                            current += 2;
                        }
                        else
                            current += 1;
                        MetaphAdd(primary, 'T');
                        break;
                    case 'V':
                        if (ins.ToCharArray()[current + 1] == 'V')
                            current += 2;
                        else
                            current += 1;
                        MetaphAdd(primary, 'F');
                        break;
                    case 'W':
                        if (stringAt(ins, current, 2, list88))
                        {
                            MetaphAdd(primary, 'R');
                            current += 2;
                            break;
                        }
                        if ((current == 0) && (isVowel(ins, current + 1, length) || stringAt(ins, current, 2, list89)))
                        {
                            MetaphAdd(primary, 'A');
                        }
                        if (((current == last) && isVowel(ins, current - 1, length)) || stringAt(ins, current - 1, 5, list90) || stringAt(ins, 0, 3, list91))
                        {
                            MetaphAdd(primary, 'F');
                            current += 1;
                            break;
                        }
                        if (stringAt(ins, current, 4, list92))
                        {
                            MetaphAdd(primary, "TS");
                            current += 4;
                            break;
                        }
                        current += 1;
                        break;
                    case 'X':
                        if (!((current == last) && (stringAt(ins, current - 3, 3, list93) || stringAt(ins, current - 2, 2, list94))))
                            MetaphAdd(primary, "KS");
                        if (stringAt(ins, current + 1, 1, list95))
                            current += 2;
                        else
                            current += 1;
                        break;
                    case 'Z':
                        if (ins.ToCharArray()[current + 1] == 'H')
                        {
                            MetaphAdd(primary, 'J');
                            current += 2;
                            break;
                        }
                        else
                        {
                            MetaphAdd(primary, 'S');
                        }
                        if (ins.ToCharArray()[current + 1] == 'Z')
                            current += 2;
                        else
                            current += 1;
                        break;
                    default:
                        current += 1;
                        break;
                }
            }
            return primary.ToString();
        }      

        #endregion
    }
}
